package com.aerfafish.spider.spider;

import com.aerfafish.spider.callback.SpiderCallback;
import com.aerfafish.spider.neo4j.dao.Company;
import com.aerfafish.spider.neo4j.dao.CompanyHoldShare;
import com.aerfafish.spider.utils.RequestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Html;
import us.codecraft.webmagic.selector.Selectable;

import java.util.Calendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CompanySpider implements PageProcessor {

    private final static Logger logger = LoggerFactory.getLogger(CompanySpider.class);

    private Spider spider = Spider.create(this).setExitWhenComplete(false).thread(5);

    private SpiderCallback spiderCallback;

    public CompanySpider(SpiderCallback spiderCallback) {
        this.spiderCallback = spiderCallback;
        spider.start();
    }

    @Override
    public void process(Page page) {
        String companyCode = null;

        if (page.getUrl().regex("^http://fund\\.eastmoney\\.com/Company/tzzh/GsccQuarter").match()) {
            Pattern fundCodePattern = Pattern.compile("(gsId=)([0-9]*)");
            Matcher matcher = fundCodePattern.matcher(page.getUrl().get());

            try {
                if (matcher.find()) {
                    companyCode = matcher.group(2);
                } else {
                    logger.error("fundcode not match");
                    return;
                }

                if (companyCode == null) {
                    logger.error("fund code is null.");
                    return;
                }

            } catch (Exception e) {
                logger.error(page.getUrl().get(), e);
                return;
            }

            parseShareInfo(companyCode, page.getHtml());
        }

    }

    @Override
    public Site getSite() {
        return Site.me().setCycleRetryTimes(3000).setSleepTime(10).setCharset("UTF-8").setTimeOut(20000)
                .setUserAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36");
    }

    public void spiderCompany(String companyCode) {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH )+1;
        if (month <= 3) {
            // 爬取上一年数据
            spiderShareInfo(companyCode, year-1, 4);
        } else if (month <= 6){
            spiderShareInfo(companyCode, year, 1);
        } else if (month <= 9){
            spiderShareInfo(companyCode, year, 2);
        } else {
            spiderShareInfo(companyCode, year, 3);
        }
    }

    public void spiderShareInfo(String companyCode, Integer year, Integer quarter) {
        String url = "http://fund.eastmoney.com/Company/tzzh/GsccQuarter?gsId=%s&year=%s&quarter=%s&ftype=0";
        spider.addRequest(RequestUtil.urlToRequest(String.format(url, companyCode, year, quarter),
                String.format("http://fund.eastmoney.com/Company/f10/gscc_%s.html", companyCode)));

    }



    private void parseShareInfo(String companyCode, Html data) {
        Company company = new Company();
        company.setCode(companyCode);
        spiderCallback.onSaveCompany(company);
        Selectable selectable = data.$("div.common-block-con");

        Selectable shareDatas = selectable.$("tbody").$("tr");
        for (Selectable shareData : shareDatas.nodes()) {
            CompanyHoldShare companyHoldShare = new CompanyHoldShare();
            try {
//                String shareName = shareData.$("td.tol").$("a").regex("(>)(.*)(<)", 2).toString();
                String shareCode = shareData.$("td.td-align-left").links().regex("(^http\\://quote\\.eastmoney\\.com/)(.*)(.html$)", 2).toString();
                List<String> detailed = shareData.$("td").regex("(>)(.*)(<)", 2).all();
                companyHoldShare.setProportion(Float.parseFloat(detailed.get(5).substring(0, detailed.get(5).length()-1)));
                companyHoldShare.setSharesNum(Float.parseFloat(detailed.get(6).replace(",", "")));
                companyHoldShare.setSharesValue(Float.parseFloat(detailed.get(7).replace(",", "")));
                if (shareCode != null) {
                    spiderCallback.onSaveCompanyShareRelation(companyHoldShare, companyCode, shareCode);
                }
            } catch (Exception e) {
                logger.error("parse share info error", e);
            }
        }

    }

}
